//ArrayList的使用

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class TestDemo4 {
    public static void main(String[] args) {
        //1.创建ArrayList对象
        //a.
        ArrayList<String> arrayList=new ArrayList<>();//空盒子，盒子里面没东西，但盒子本体是在的
        ArrayList<String> arrayList2=null;//连盒子都没有
        ArrayList<String> arrayList3=new ArrayList<>(10);//构造的同时，可以去指定初始容量
        //b.
        ArrayList<String> arrayList4=new ArrayList<>(arrayList);//使用arrayList复制一份，生成arrayList4
        //c.
        List<String> list=new ArrayList<>();//向上转型

        //添加元素--add方法
        list.add("aaa");//尾插
        list.add("bbb");
        list.add("ccc");
        System.out.println(list);//集合类一般都可以直接打印
        //结果：[aaa, bbb, ccc]


        //获得元素个数--集合类提供了size（）方法来获取元素个数
        System.out.println(list.size());
        //结果：3


        //获取与设置list中的元素
        System.out.println(list.get(1));//获得1下标的元素
        //结果：bbb
        //System.out.println(list.get(3));获得3下标的元素  error:IndexOutOfBoundsException
        list.set(1,"eee");//将1下标的元素设置成eee
        System.out.println(list.get(1));
        // 结果：eee
        //list.set(5,"qqq");将5下标的元素设置成qqq  error:IndexOutOfBoundsException


        //遍历list(遍历是可能进行各种操作的，不一定是为了打印)
        //a.for循环
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }
        //b.for each
        for(String s:list){
            System.out.println(s);
        }
        //c.迭代器
        Iterator<String> iterator=list.iterator();
        while(iterator.hasNext()){//判断当前下标是否小于 ArrayList 的元素个数（size）。
            System.out.println(iterator.next());//取得这个元素，指向下一个元素
        }


        //在任意位置添加元素--add
        list.add(2,"www");//注意这里下标的含义：往指定下标之前插入元素、添加完毕后新元素的下标就是这里的下标
        System.out.println(list);
        //结果：[aaa, eee, www, ccc]
        list.add(4,"vvv");//相当于尾插了
        System.out.println(list);
        //结果：[aaa, eee, www, ccc, vvv]
        //list.add(6,"vvv");error:IndexOutOfBoundsException


        //删除元素--remove
        //a.按照下标来删除
        list.remove(1);
        System.out.println(list);
        //结果：[aaa, www, ccc, vvv]
        //b.按照元素内容来删除
        list.remove("ccc");
        System.out.println(list);
        //结果：[aaa, www, vvv]
        List<Integer> list2=new ArrayList<>();
        list2.add(1);
        list2.add(2);
        list2.add(3);
        list2.add(4);
        Integer value=2;
        list2.remove(value);//删除的是元素2，因为是Integer类型


        // 通过 contains 判定元素是否存在(是通过equals方法来判定的，字符串内容相同则判定存在）
        System.out.println(list.contains("aaa"));
        //结果：true
        System.out.println(list.contains("bbb"));
        //结果：flase


        //indexOf，lastIndexOf获取元素下标(不存在返回-1)
        System.out.println(list.indexOf("aaa"));
        //结果：0
        System.out.println(list.lastIndexOf("vvv"));
        //结果：2


        //通过subList得到子列表
        List<String> subList1=list.subList(1,2);//对subList1进行操作就是在对list做操作
        System.out.println(subList1);
        //结果：[www]
        List<String> subList2=new ArrayList<>(list.subList(0,2));//subList2是独立的
        System.out.println(subList2);
        //结果：[aaa, www]


        //通过clear清空List中的元素--变成空盒子
        System.out.println("清空前："+list);
        //结果：清空前：[aaa, www, vvv]
        list.clear();
        System.out.println("清空后："+list);
        //结果：清空后：[]
    }
}

/*
在Java中，集合类是用于存储、管理和操作一组对象的数据结构的统称。集合类提供了丰富的功能，使得对对象的存储和处理更加高效和便捷。以下是关于Java集合类的详细介绍：

集合框架体系
Java集合框架主要包含了接口（Interfaces）、实现类（Implementing Classes）和算法（Algorithms）三部分：

接口：定义了集合的行为规范，如如何添加元素、删除元素、遍历元素等。例如，Collection 接口是集合框架的根接口，它有许多子接口，如 List、Set 和 Queue 等，每个子接口都有其独特的特性和用途。
List 接口：有序且可重复的集合，允许通过索引访问元素。
Set 接口：无序且不可重复的集合，每个元素最多出现一次。
Queue 接口：用于存储元素的队列，通常遵循先进先出（FIFO）的原则。
实现类：是接口的具体实现，提供了不同的数据结构来满足各种需求。例如，ArrayList 和 LinkedList 是 List 接口的实现类，HashSet 和 TreeSet 是 Set 接口的实现类，PriorityQueue 是 Queue 接口的实现类。
ArrayList：基于动态数组实现，适合随机访问元素，但在插入和删除操作时效率较低。
LinkedList：基于双向链表实现，适合频繁的插入和删除操作，但随机访问效率不如 ArrayList。
HashSet：基于哈希表实现，能快速判断元素是否存在，插入和查询操作效率高。
TreeSet：基于红黑树实现，能保证元素按照自然顺序或自定义顺序排序。
算法：集合框架提供了一系列静态方法来操作集合，如排序、查找、反转等。这些算法定义在 Collections 类中，例如 Collections.sort() 方法可以对 List 进行排序。
集合类的作用
存储和管理对象：可以方便地存储多个对象，并对这些对象进行集中管理。例如，在一个学生管理系统中，可以使用集合来存储所有学生的信息。
数据结构多样化：不同的集合实现类提供了不同的数据结构，开发人员可以根据具体的需求选择合适的集合类。比如，需要快速查找元素时可以选择 HashSet 或 HashMap；需要保持元素的插入顺序时可以使用 LinkedList 或 LinkedHashSet。
提高代码复用性：集合框架提供了统一的接口和方法，使得对不同类型集合的操作变得更加一致和简单，减少了重复代码的编写。
 */


/*
在Java中，Iterator 接口定义了用于遍历集合元素的方法。Iterator 接口中包含以下几个主要方法：

hasNext() 方法
功能描述：用于判断集合中是否还有下一个元素。它会检查迭代器当前位置之后是否存在元素，如果存在则返回 true，否则返回 false。
在上述代码中，while (iterator.hasNext()) 循环条件使用 hasNext() 方法来判断是否还有下一个元素，只要还有元素，循环就会继续执行。

next() 方法
功能描述：返回集合中的下一个元素，并将迭代器的位置向前移动一个元素。如果迭代器已经到达集合的末尾，调用 next() 方法会抛出 NoSuchElementException 异常。
示例代码：上述代码中的 String element = iterator.next(); 这一行就使用了 next() 方法来获取当前位置的元素，并将迭代器移动到下一个位置。
remove() 方法
功能描述：从迭代器指向的集合中移除当前迭代器返回的最后一个元素（可选操作）。在调用 next() 方法之后，才能调用 remove() 方法。多次调用 remove() 方法可能会导致不可预测的行为，除非在两次调用之间再次调用 next() 方法。如果调用 remove() 方法时没有遵循这些规则，会抛出 IllegalStateException 异常。
这些方法使得 Iterator 能够有效地遍历和修改集合中的元素，为集合操作提供了统一且便捷的方式。
 */

/*
`iterator.hasNext()` 的实现逻辑依赖于具体集合类对 `Iterator` 接口的实现。不同的集合类（如 `ArrayList`、`LinkedList`、`HashSet` 等）有不同的数据结构和存储方式，因此其实现细节会有所差异，但总体思路是相似的。以下以常见的 `ArrayList` 为例来讲解其大致实现逻辑：

### `ArrayList` 中 `hasNext()` 的实现逻辑
`ArrayList` 是基于动态数组实现的列表。它的迭代器 `Itr` 内部维护了一个指向当前元素位置的游标变量（通常命名为 `cursor`）。

1. **初始化迭代器**：当创建 `ArrayList` 的迭代器时，`cursor` 初始化为 `0`，表示迭代器位于列表的开头之前。

2. **`hasNext()` 方法的实现**：
   - `hasNext()` 方法的核心逻辑是检查 `cursor` 的值是否小于 `ArrayList` 的元素个数（`size`）。
   - 如果 `cursor` 小于 `size`，说明在当前位置之后还有元素，`hasNext()` 方法返回 `true`；否则，表示已经到达列表末尾，没有下一个元素了，`hasNext()` 方法返回 `false`。

以下是简化的 `ArrayList` 迭代器中 `hasNext()` 方法的代码示例（实际的 `ArrayList` 源码中迭代器的实现更复杂，但核心逻辑类似）：

```java
import java.util.ArrayList;
import java.util.List;

class ArrayListIterator<E> implements java.util.Iterator<E> {
    private final ArrayList<E> list;
    private int cursor; // 指向当前元素的下一个位置

    public ArrayListIterator(ArrayList<E> list) {
        this.list = list;
        this.cursor = 0;
    }

    @Override
    public boolean hasNext() {
        return cursor < list.size();
    }

    @Override
    public E next() {
        if (!hasNext()) {
            throw new java.util.NoSuchElementException();
        }
        E element = list.get(cursor);
        cursor++;
        return element;
    }

    // remove 方法省略
}

public class ArrayListIteratorExample {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("Apple");
        list.add("Banana");
        list.add("Cherry");

        java.util.Iterator<String> iterator = new ArrayListIterator<>(list);
        while (iterator.hasNext()) {
            String element = iterator.next();
            System.out.println(element);
        }
    }
}
```

在上述代码中，`ArrayListIterator` 类实现了 `Iterator` 接口。`hasNext()` 方法通过比较 `cursor` 和 `list.size()` 来判断是否有下一个元素。

### 其他集合类中 `hasNext()` 的实现逻辑
 - **`LinkedList`**：`LinkedList` 基于双向链表实现。其迭代器内部维护了一个指向当前节点的引用。`hasNext()` 方法通过检查当前节点的下一个节点是否为 `null` 来判断是否有下一个元素。如果下一个节点不为 `null`，则返回 `true`，否则返回 `false`。
 - **`HashSet`**：`HashSet` 基于哈希表实现。它的迭代器遍历哈希表中的桶（bucket）和链表（如果有冲突）。`hasNext()` 方法会先检查当前桶是否遍历完，如果当前桶遍历完了，就移动到下一个非空的桶，然后判断是否有下一个元素。通过这种方式来确定是否还有下一个元素可供遍历。

虽然不同集合类的 `hasNext()` 方法实现细节不同，但都是围绕如何判断在当前遍历位置之后是否还有元素这一核心逻辑展开的。
 */